home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / DDJ0992.ARJ / DBISR.ASM < prev    next >
Assembly Source File  |  1992-07-13  |  47KB  |  1,042 lines

  1. ;dbisr.asm
  2. ;Debugger interrupt service routines
  3. ;
  4. ;---------------------------------------------------------------------------- 
  5. ;Copyright 1991, 1992 ASMicro Co. 
  6. ;7/6/91       Rick Knoblaugh
  7. ;-----------------------------------------------------------------------------
  8.                 .386P
  9.                 include dbequ.inc
  10.                 include dbmac.inc
  11.                 include dbstruc.inc
  12.  
  13.  
  14. data            segment para public 'data16' use16
  15.                 extrn   io_table:byte, IO_TAB_ENTRIES:abs, 
  16.                 extrn   int1_active:byte, display_loc:word
  17.                 extrn   trace_count:word, wrk_vid_offset:word
  18.                 extrn   num_int_bp:byte, int_bpdat:byte, num_io_bp:byte
  19.                 extrn   io_instrucf:byte, io_inst_port:word, io_inst_info:byte
  20.                 extrn   tuser_cs:word, tuser_ip:word, trap_clear:byte
  21.                 extrn   num_table:byte  
  22. data            ends                   
  23.            
  24. gdt_seg         segment para public 'data16' use16
  25.                 extrn   sel_databs:byte      
  26.                 extrn   sel_video:byte
  27.                 extrn   sel_data:byte
  28.                 extrn   sel_tss_alias:byte
  29. gdt_seg         ends                              
  30.  
  31. tss_seg         segment para public 'data16' use16
  32. tss_seg         ends                              
  33.  
  34. zcode   segment para public 'code16' use16
  35.                 extrn   int_9_isr:proc, int_1_isr:proc
  36. zcode           ends
  37.  
  38.  
  39. isrcode         segment para public 'icode16' use16
  40.                 assume cs:isrcode, ds:nothing, es:nothing
  41. ;--------------------------------------------------------------
  42. ;PUBLICS                                                      |
  43. ;--------------------------------------------------------------
  44.                 public  int_1, int_0, int_2, int_3, int_4, int_5
  45.                 public  int_6, int_7, except_8, except_9, except_0ah
  46.                 public  except_0bh, except_0ch, except_0dh, except_0eh
  47.                 public  except_0fh, int_20h, int_21h, int_22h, int_23h
  48.                 public  int_24h, int_25h, int_26h, int_27h
  49.  
  50.                 public  int_70h, int_71h, int_72h, int_73h
  51.                 public  int_74h, int_75h, int_76h, int_77h
  52.  
  53. ;--------------------------------------------------------------
  54. ;Interrupt Service Routines                                   |
  55. ;--------------------------------------------------------------
  56.                 irp     z, <0, 2, 3, 4, 5, 6, 7>
  57.                 DOINT   &z
  58.                 endm
  59.  
  60.                 irp     z, <8, 9, 0ah, 0bh, 0ch, 0dh, 0eh, 0fh>
  61.                 DOEXCP  &z
  62.                 endm
  63.  
  64.                 irp     z, <20h, 22h, 23h, 24h, 25h, 26h, 27h>
  65.                 DOEXCPH &z 
  66.                 endm
  67.  
  68.                 irp     z, <70h, 71h, 72h, 73h, 74h, 75h, 76h, 77h>
  69.                 DOINT   &z 
  70.                 endm     
  71.  
  72. int_1           proc    far
  73.                 push    bp
  74.                 push    1                       ;indicate it is int 1
  75.                 mov     bp, sp
  76.                 pushad
  77.                 mov     ax, offset gdt_seg:sel_data
  78.                 mov     ds, ax
  79.                 assume  ds:data
  80.  
  81.                 mov     eax, dr6                ;get debug status register
  82.                 bt      eax, deb_stat_bs         
  83.                 jc      int_1_100               ;if single step trap
  84.  
  85.                 test    al, 0fh                 ;look at bn status
  86.                 jnz     short int_1_200         ;if debug reg caused break
  87. int_1_100:                                      ;enter the debugger
  88.                 cmp     trace_count, 1          ;is debugger tracing?
  89.                 jae     short int_1_200         ;if so, go back into debugger
  90.                 cmp     io_instrucf, TRUE       ;break caused by I/O ?
  91.                 je      short int_1_200         ;if so, go into debugger
  92.  
  93.                 xor     eax, eax
  94.                 mov     dr6, eax                ;clear debug status       
  95.  
  96.                 popad
  97.                 jmp     pass_thru               ;go to user's debugger
  98.  
  99. int_1_200:                                      
  100.  
  101.                 cmp     int1_active, TRUE       ;should never be!!!!!!
  102.                 jne     short int_1_210
  103.  
  104.                 mov     ax, offset gdt_seg:sel_video
  105.                 mov     es, ax
  106.                 mov     di, wrk_vid_offset
  107.                 cld
  108.                 mov     al, 'B'
  109.                 stosb
  110.                 inc     di
  111.                 mov     al, 'U'
  112.                 stosb
  113.                 inc     di
  114.                 mov     al, 'G'
  115.                 stosb
  116.                 inc     di
  117.                 jmp     $
  118.  
  119. int_1_210:                             ;<=======also JMPed to by gen_prot_isr
  120.  
  121.                 call    adjust_ustack          ;make return spot on user stack
  122. ;
  123. ;returns with [esi][edx] pointing to user stack area
  124. ;
  125. ;Create an IRET address on user stack so that IRET from int 1 will
  126. ;return to current cs:ip.  Change return address on PL0 stack so that
  127. ;IRETD will return to debugger's int 1 handler.                       
  128. ;
  129. ;
  130.  
  131.                 mov     ax, [bp].s_cs           ;put on user cs
  132.                 mov     [esi][edx].user_cs, ax
  133.                 mov     eax, [bp].s_eip         ;put on ip
  134.                 mov     [esi][edx].user_ip, ax
  135.  
  136.                 mov     ax, offset int_1_isr
  137.                 movzx   eax, ax
  138.                 mov     [bp].s_eip, eax                     
  139.                 mov     ax, zcode
  140.                 mov     [bp].s_cs, ax
  141.                 mov     ax, offset gdt_seg:sel_data
  142.                 mov     ds, ax
  143.                 assume  ds:data
  144.                 mov     int1_active, TRUE       ;make debugger active
  145.                 assume  ds:nothing
  146.  
  147.                 popad
  148.                 add     sp, 2                   ;get rid of int number
  149.                 pop     bp
  150.                 iretd                  
  151.  
  152. int_1           endp
  153.  
  154. ;--------------------------------------------------------------
  155. ;int_21h - "int 9" ISR.  If debugger is active, pass control  |
  156. ;          to debugger's int 9 routine.  Otherwise, look for  |
  157. ;          the hot key.  If not pressed, go to regular int 9  |
  158. ;          ISR via the interrupt vector table.                |
  159. ;                                                             |
  160. ;          If hot key is pressed, set sel_data:int1_active    |
  161. ;          and fix stack so that debugger will be entered.    |
  162. ;                                                             |
  163. ;--------------------------------------------------------------
  164. int_21h         proc    far
  165.                 push    bp
  166.                 push    9
  167.                 mov     bp, sp
  168.  
  169.                 pushad
  170.                 mov     ax, offset gdt_seg:sel_data
  171.                 mov     ds, ax
  172.                 assume  ds:data
  173.                 cmp     int1_active, TRUE       ;is debugger active?
  174.                 assume  ds:nothing
  175.                 jne     short int_21h_100       ;if not, look for hot key
  176.  
  177.                 call    adjust_ustack           ;make return spot on user stack
  178. ;
  179. ;returns with [esi][edx] pointing to user stack area
  180. ;
  181. ;Create an IRET address on debugger's PL3 stack so that IRET from int 9 will
  182. ;return to current cs:ip.  Change return address on PL0 stack so that
  183. ;IRETD will return to debugger's int 9 handler.                       
  184. ;
  185. ;
  186.                 mov     ax, [bp].s_cs           ;put on debugger cs
  187.                 mov     [esi][edx].user_cs, ax
  188.                 mov     eax, [bp].s_eip         ;put on ip
  189.                 mov     [esi][edx].user_ip, ax
  190.  
  191.                 mov     ax, offset int_9_isr
  192.                 movzx   eax, ax
  193.                 mov     [bp].s_eip, eax                     
  194.                 mov     ax, zcode
  195.                 mov     [bp].s_cs, ax
  196.  
  197.                 jmp     short int_21h_999
  198. int_21h_100:
  199.  
  200.                 mov     ax, offset gdt_seg:sel_databs 
  201.                 mov     ds, ax
  202.                 mov     bx, KBD_FLAG
  203.                 mov     al, [bx + 400h]         ;bios data area
  204.                 and     al, LR_SHIFT
  205.                 cmp     al, LR_SHIFT
  206.                 je      short int_21h_200
  207.                 popad
  208.                 jmp     pass_thru               ;if not hot key go do   
  209.                                                 ;regular int 9
  210.  
  211. int_21h_200:
  212.                 mov     ax, offset gdt_seg:sel_data
  213.                 mov     ds, ax
  214.                 assume  ds:data
  215.                 mov     int1_active, TRUE       ;debugger active 
  216.                 assume  ds:nothing
  217.                 call    adjust_ustack          ;make return spot on user stack
  218. ;
  219. ;returns with [esi][edx] pointing to user stack area
  220. ;
  221. ;Create an IRET address on user stack so that IRET from int 1 will
  222. ;return to current cs:ip.
  223.  
  224.                 mov     ax, [bp].s_cs           ;put on user cs
  225.                 mov     [esi][edx].user_cs, ax
  226.                 mov     eax, [bp].s_eip         ;put on ip
  227.                 mov     [esi][edx].user_ip, ax
  228.  
  229. ;Change return address on PL0 stack so that IRETD will return to old
  230. ;int 9 handler.                       
  231. ;
  232.                 mov     bx, (9 * 4)             ;get int vector
  233.                 movzx   eax, [bx].d_offset      ;offset portion
  234.                 mov     [bp].s_eip, eax                     
  235.                 mov     ax, [bx].d_seg          ;segment portion
  236.                 mov     [bp].s_cs, ax
  237.  
  238.                 call    adjust_ustack           ;make return spot on user stack
  239.  
  240. ;Create an IRET address on user stack so that IRET from int 9 will
  241. ;return to debugger's int 1. 
  242.  
  243.                 mov     ax, zcode
  244.                 mov     [esi][edx].user_cs, ax
  245.                 mov     ax, offset int_1_isr
  246.                 mov     [esi][edx].user_ip, ax
  247.  
  248. int_21h_999:
  249.                 popad
  250.                 add     sp, 2                   ;get rid of int number
  251.                 pop     bp
  252.                 iretd                  
  253.  
  254.  
  255. int_21h         endp
  256. ;--------------------------------------------------------------
  257. ;do_bit_map - For the number of ports specified, clear/set    | 
  258. ;             corresponding I/O permission map bits.          |
  259. ;                                                             |
  260. ;             Enter:  Ah = 0 clear, ah = 1 set                |
  261. ;                     dx = starting port                      |
  262. ;                     cx = number of ports                    |
  263. ;  All registers saved.                                       |
  264. ;--------------------------------------------------------------
  265. do_bit_map      proc    near   
  266.                 push    ax
  267.                 push    bx
  268.                 push    cx
  269.                 push    dx
  270.                 mov     bx, offset gdt_seg:sel_tss_alias
  271.                 mov     ds, bx
  272.                 assume  ds:tss_seg
  273.                 mov     bx, t_iomap 
  274.                 push    cx
  275.                 mov     cx, dx                  ;port               
  276.                 and     cl, 7                   ;get non byte boundary
  277.                 mov     al, 1                   ;first bit position
  278.                 shl     al, cl                  ;get out corresponding bit
  279.                 shr     dx, 3                   ;start_port/8
  280.                 pop     cx
  281.                 add     bx, dx                  ;starting offset in map
  282. do_bit100:
  283.                 or      ah, ah                  
  284.                 jnz     short do_bit200
  285.                 mov     dl, al
  286.                 not     dl
  287.                 and     byte ptr [bx], dl       ;turn off permission bit
  288.                 jmp     short do_bit250
  289. do_bit200:
  290.                 or byte ptr [bx], al            ;turn on permission bit
  291. do_bit250:
  292.                 rcl     al, 1                   ;next bit position
  293.                 jnc     short do_bit300
  294.                 inc     bx
  295.                 rcl     al, 1
  296. do_bit300:
  297.                 loop    do_bit100
  298.                 pop     dx
  299.                 pop     cx
  300.                 pop     bx
  301.                 pop     ax
  302.                 ret
  303. do_bit_map      endp        
  304.  
  305.  
  306. ;--------------------------------------------------------------
  307. ;except_handler - Process as follows:                         |
  308. ;                                                             |
  309. ;                      Int 0dh - Go look for software int or  |
  310. ;                                I/O instruction.             |
  311. ;                    Any other                                |
  312. ;                    exception - Go display exception number  |
  313. ;                                and halt.                    |
  314. ;--------------------------------------------------------------
  315. except_handler  proc    near
  316.                 mov     bp, sp
  317.                 cmp     [bp].e_pushed_int , GEN_PROT_EXCEP
  318.                 je      gen_prot_isr
  319.                 mov     ax, [bp].e_pushed_int ;int in ax
  320. ;fall through to fatal_error
  321. except_handler  endp
  322.  
  323.  
  324. fatal_error:
  325.                 call    display_it
  326.                 jmp     $
  327.  
  328.  
  329. ;--------------------------------------------------------------
  330. ;display_it - Display hex number on screen at next display    |
  331. ;             offset of video page 0.  This is used for       |
  332. ;             debugging.                                      |
  333. ;                                                             |
  334. ;             Enter:  number in AX                            |
  335. ;                                                             |
  336. ;              Exit:  sel_data:display_loc will contain       |
  337. ;                     location on screen for next display.    |
  338. ;                                                             |
  339. ;             All registers saved                             |
  340. ;--------------------------------------------------------------
  341. display_it      proc    near
  342.                 pusha
  343.                 push    ds
  344.                 push    es
  345.  
  346.                 mov     dx, offset gdt_seg:sel_data
  347.                 mov     ds, dx                  ;get our data segment
  348.                 assume  ds:data
  349.                 mov     dx, offset gdt_seg:sel_video
  350.                 mov     es, dx                  ;and video segment
  351.                 mov     di, display_loc
  352.                 call    put_hex_word
  353.                 add     di, 2                   ;past space and attribute
  354.                 cmp     di, PAGE_SIZE - 100h    ;at bottom of screen?
  355.                 jb      short display_i100
  356.                 xor     di, di                  ;if so, back to start of page
  357. display_i100:
  358.                 mov     display_loc, di
  359.                 pop     es
  360.                 pop     ds
  361.                 popa
  362.                 ret
  363. display_it      endp        
  364.  
  365. put_hex_word:
  366.                 mov     dl, al                  ;save LSB
  367.                 mov     al, ah                  ;want to print MSB first        
  368.                 call    put_hex_byte
  369.                 mov     al, dl
  370.  
  371. put_hex_byte:                
  372.                 mov     ah, al
  373. put_hex_100:
  374.                 shr     al, 4                   ;get high portion
  375.                 call    put_nibble
  376.                 mov     al, ah
  377.                 and     al, 0fh      
  378. put_nibble:
  379.                 mov     bx, offset num_table
  380.                 xlat
  381.                 stosb
  382.                 inc     di                      ;past attribute
  383.                 ret
  384.  
  385. ;--------------------------------------------------------------
  386. ;pass_thru - This procedure is JMPed to by any interrupt      |
  387. ;            handler which wishes to pass control to the      |
  388. ;            original ISR per the interrupt vector table.     |
  389. ;                                                             |
  390. ;            Also, it checks to see if there are any break    |
  391. ;            points set on the int.  If there are, the int    |
  392. ;            being passed through is checked to see if it     |
  393. ;            matches the condition for the break point.  If   |
  394. ;            the condition for the break point is met, DR0    |
  395. ;            is used to cause a break at the ISR.             |
  396. ;                                                             |
  397. ;            Enter:                                           |
  398. ;                  See stack_area struc for stack layout      |
  399. ;                  Any error code has been removed from stack.|
  400. ;                  EIP on stack has been adjusted if          |
  401. ;                  necessary.                                 |
  402. ;--------------------------------------------------------------
  403. pass_thru       proc    near
  404.                 mov     bp, sp
  405.                 pushad
  406.                 call    adjust_ustack           ;adjust user stack
  407. ;
  408. ;returns with [esi][edx] pointing to user stack area
  409. ;
  410.                 mov     cx, [bp].s_cs           ;put on user cs
  411.                 mov     [esi][edx].user_cs, cx
  412.                 mov     ecx, [bp].s_eip         ;put on ip
  413.                 mov     [esi][edx].user_ip, cx
  414.                 movzx   ebx, [bp].s_pushed_int  ;get int number
  415.  
  416.                 movzx   ecx, [ebx * 4].d_offset ;offset portion
  417.                 mov     [bp].s_eip, ecx                     
  418.                 mov     cx, [ebx * 4].d_seg     ;segment portion
  419.                 mov     [bp].s_cs, cx
  420. pass_thru200:
  421.  
  422.                 mov     cx, offset gdt_seg:sel_data
  423.                 mov     fs, cx
  424.                 assume  fs:data
  425.                 push    fs     
  426.                 cmp     fs:trap_clear, TRUE     ;tracing through an int?
  427.                 jne     short pass_thru500            
  428.                 mov     fs:trap_clear, FALSE    ;reset it
  429.                 mov     fs:int1_active, TRUE    ;debugger active 
  430. ;
  431. ;If tracing through a software INT instruction, don't want the INT to
  432. ;be treated as one instruction (trap flag is cleared upon entering
  433. ;interrupts).  In order to single step starting with the first instruction
  434. ;of the ISR, move address of the first instruction onto the user's stack 
  435. ;and make user cs:ip on PL0 stack point to debugger int 1.
  436. ;
  437.                 sub     edx, 6                  ;flags, cs, ip
  438.                 mov     [bp].s_esp, edx         ;adjust it
  439.                 mov     ecx, [bp].s_eflags      ;put on flags
  440.                 mov     [esi][edx].user_flags, cx
  441.                 mov     cx, [bp].s_cs           ;put &ISR onto user's stack
  442.                 mov     [esi][edx].user_cs, cx  
  443.                 mov     ecx, [bp].s_eip         
  444.                 mov     [esi][edx].user_ip, cx
  445.  
  446.                 mov     cx, ZCODE               
  447.                 mov     [bp].s_cs, cx           
  448.                 mov     cx, offset int_1_isr 
  449.                 movzx   ecx, cx
  450.                 mov     [bp].s_eip, ecx
  451.  
  452. pass_thru500:
  453.                 pop     ds                      ;get data seg (was fs)
  454.                 assume  ds:data
  455.  
  456.                 cmp     int1_active, TRUE       ;is debugger active?
  457.                 je      short pass_thru999      ;if so, don't even think
  458.                                                 ;of breaking        
  459.  
  460.                 movzx   cx, num_int_bp          ;number of defined int breaks
  461.                 jcxz    pass_thru999            ;if no int type break points
  462.                 mov     si, offset int_bpdat 
  463. pass_thru700:
  464.                 cmp     [si].int_stat, ACTIVE   ;is break on int enabled?
  465.                 jne     short pass_thru800
  466.                 dec     cx
  467.                 cmp     [si].int_num, bl        ;is this the int specified?
  468.                 jne     short pass_thru800
  469.                 cmp     [si].int_reg, NO_CONDITION ;no conditions?
  470.                 je      short pass_thru750      ;if none go ahead and set break
  471.                 mov     dx, [si].int_val        ;get data for comparison
  472.                 cmp     [si].int_reg, INT_AL_COMP ;condition compare on al?
  473.                 jne     short pass_thru730
  474.                 cmp     al, dl                  ;condition met?
  475.                 je      pass_thru750           ;if so, go ahead and set break
  476.                 jmp     short pass_thru800     ;if != look for more conditions 
  477. pass_thru730:
  478.                 cmp     [si].int_reg, INT_AH_COMP ;condition compare on ah?
  479.                 jne     short pass_thru740
  480.                 cmp     ah, dl                 ;condition met
  481.                 je      short pass_thru750     ;if so, go ahead and set break
  482.                 jmp     short pass_thru800     ;if != look for more conditions 
  483. pass_thru740:                                  ;condition compare on ax
  484.                 cmp     ax, dx
  485.                 jne     short pass_thru800     ;if != look for more conditions 
  486. pass_thru750:
  487.                 mov     ebx, [bp].s_eip         ;get offset and
  488.                 movzx   edx, [bp].s_cs          ;segment of ISR
  489.                 shl     edx, 4                  ;convert to linear
  490.                 add     edx, ebx
  491.  
  492.                 mov     ch, 1                   ;set debug register
  493.                 mov     al, DEB_DAT_LEN1        ;exec breaks use 1 byte length
  494.                 mov     ah, DEB_TYPE_EXEC
  495.                 sub     cl, cl                  ;debug reg zero 
  496.                 call    do_debug_reg
  497.                 jmp     short pass_thru999
  498.  
  499. pass_thru800:
  500.                 add     si, size info_int       ;advance to next int break
  501.                 or      cl, cl                  ;all int breaks checked?
  502.                 jnz     short pass_thru700      ;if not, check the next one
  503.  
  504. pass_thru999:                         
  505.                 popad
  506.                 add     sp, 2                   ;get rid of int number
  507.                 pop     bp
  508.                 iretd                  
  509. pass_thru       endp        
  510.  
  511. ;--------------------------------------------------------------
  512. ;adjust_ustack - Make room for flags and a far address on the |
  513. ;                user stack.  Place flags from PL0 stack      |
  514. ;                on user stack.  The caller of this routine   |
  515. ;                will then place the far address on the user  |
  516. ;                stack.                                       |
  517. ;                                                             |
  518. ;            Enter:                                           |
  519. ;                  bp=base of PL0 stack                       |
  520. ;             Exit:                                           |
  521. ;                 esi=linear address of user stack segment    |
  522. ;                 edx=adjusted user sp                        |
  523. ;                  ds=absolute zero selector                  |
  524. ;                                                             |
  525. ;    No registers saved (AX not used)                         |
  526. ;--------------------------------------------------------------
  527. adjust_ustack   proc    near
  528.                 mov     cx, offset gdt_seg:sel_databs
  529.                 mov     ds, cx
  530.                 movzx   esi, [bp].s_ss          ;user stack
  531.                 shl     esi, 4                  ;make linear
  532.                 mov     edx, [bp].s_esp         ;user stack pointer
  533.                 sub     edx, 6                  ;flags, cs, ip
  534.                 mov     [bp].s_esp, edx         ;adjust it
  535.                 mov     ecx, [bp].s_eflags      ;put on flags
  536.                 mov     [esi][edx].user_flags, cx
  537. ;
  538. ;Change flags on stack so that original ISR will be entered with 
  539. ;interrupts cleared and trap flag cleared to be consistent with their
  540. ;state upon entering an ISR (the normal way).
  541. ;
  542. ;
  543.                 and     ecx, not ( (mask resumef) OR (mask inter) OR (mask trapf)) 
  544.                 mov     [bp].s_eflags, ecx      ;put back flags
  545.                 ret
  546. adjust_ustack   endp
  547.  
  548.  
  549. ;--------------------------------------------------------------
  550. ;gen_prot_isr - JMP here if int 0dh.                          | 
  551. ;                                                             |
  552. ;               Look for software int.  If a software int     |
  553. ;               caused the exception then:                    |
  554. ;                                                             |
  555. ;               If debugger is active, look for user software |
  556. ;               interrupts issued by PL3 layer of debugger.   |
  557. ;                                                             |
  558. ;               If int 15h function 89h deny.                 |
  559. ;                                                             |
  560. ;               If int 15h function 87h, emulate it.          |
  561. ;                                                             |
  562. ;               If none of these, simply route the interrupt  |
  563. ;               per the real mode interrupt vector table.     |
  564. ;                                                             |
  565. ;               If exception was not caused by a software     |
  566. ;               int and there are break points defined on     |
  567. ;               I/O accesses, look for I/O instruction.  If   |
  568. ;               it is an I/O instruction, temporarily clear   |
  569. ;               the corresponding TSS I/O permission bit map  |
  570. ;               bit and set trap flag to single step through  |
  571. ;               the instruction.                              |
  572. ;                                                             |
  573. ;               If other than software int or I/O, display    |
  574. ;               cs:ip, 0dh and then halt.                     |
  575. ;                                                             |
  576. ;--------------------------------------------------------------
  577. gen_prot_isr    proc    near
  578.                 pushad        
  579. ;
  580. ;Note:  Don't use DX or AX below as DX may contain an I/O port address and
  581. ;       in the case of a software interrupt, AH will have a function code.
  582. ;       Also, don't use SI or CX as they are inputs for the extended memory
  583. ;       block move function
  584. ;
  585.                 mov     bx, offset gdt_seg:sel_databs 
  586.                 mov     ds, bx
  587.                 movzx   ebx, [bp].e_cs  ;get cs of user instruction
  588.                 shl     ebx, 4          ;make linear
  589.                 add     ebx, [bp].e_eip ;add ip 
  590.                 mov     bx, [ebx]       ;get bytes at cs:ip
  591.  
  592.                 mov     di, offset gdt_seg:sel_data
  593.                 mov     ds, di          ;debugger's data
  594.  
  595.                 cmp     bl, INT_OPCODE
  596.                 je      short gen_prot020           
  597.  
  598.                 cmp     bl, INT3_OPCODE
  599.                 jne     gen_prot150     ;go look for I/O instruction
  600.                 mov     bh, 3           ;interrupt 3
  601.  
  602. gen_prot020:
  603.  
  604.                 cmp     trace_count, 0  ;is debugger tracing?
  605.                 je      short gen_prot040 ;if not, skip test below
  606.  
  607. ;See if this software interrupt is the instruction through which the user
  608. ;is tracing.  If it is, set flag.
  609.  
  610.                 mov     di, [bp].e_cs 
  611.                 cmp     di, tuser_cs
  612.                 jne     short gen_prot040
  613.                 mov     edi, [bp].e_eip 
  614.                 cmp     di, tuser_ip
  615.                 jne     short gen_prot040
  616. ;
  617. ;Clear trap bit so that it will not be set on user stack.  
  618. ;Note:  If user is doing a "trace n" where n is a number of instructions
  619. ;exceeding the number of instructions in the ISR, instructions executing upon
  620. ;return from the ISR will still be trapped through as the int 1 code will
  621. ;again set the trap flag.
  622. ;
  623.                 btr     [bp].e_eflags, trapf
  624.                 mov     trap_clear, TRUE
  625. gen_prot040:
  626.                 inc     [bp].e_eip      ;get past the 0cdh (or 0cch)
  627.                 cmp     bh, 3           ;int 3?
  628.                 je      short gen_prot060 ;if so, only 1 byte
  629. gen_prot050:                
  630.                 inc     [bp].e_eip 
  631. gen_prot060:                
  632.  
  633. ;
  634. ;See if the debugger is active and if this software interrupt is one of the
  635. ;ones used by the PL3 portion of the debugger to get PL0 services.
  636. ;
  637.                 cmp     int1_active, TRUE       ;is debugger active?
  638.                 jne     short gen_prot085
  639.  
  640. ;
  641. ;Note:  In the event that an interrupt occuring while debugger is active
  642. ;       (e.g. timer) actually uses these user software interrupts,
  643. ;       code to verify caller would need to be added here.    
  644. ;
  645.  
  646.                 cmp     bh, 60h                 ;do debug registers?
  647.                 jne     short gen_prot080
  648.  
  649.                 popad
  650.                 call    do_debug_reg 
  651.                 jmp     gen_prot299 
  652.  
  653. gen_prot080:
  654.                 cmp     bh, 61h                 ;do I/O bit map?
  655.                 jne     short gen_prot085
  656.  
  657.                 popad
  658. ;
  659. ;Unlike the accessing of debug registers, PL3 code could actually manipulate
  660. ;the TSS I/O bit map directly.  However, this interface keeps this in 
  661. ;one location.
  662. ;
  663.                 call    do_bit_map      
  664.                 jmp     gen_prot299 
  665.  
  666.  
  667. gen_prot085:
  668.                 cmp     bh, 15h                 ;int 15?
  669.                 jne     short gen_prot100
  670.                 cmp     ah, 89h                 ;request for protected mode?
  671.                 jne     short gen_prot090
  672.                                                 ;if so, can't allow
  673.                 bts     [bp].e_eflags, carry    ;set carry
  674.                 popad
  675.                 jmp     gen_prot299             ;and return
  676. gen_prot090:
  677.                 cmp     ah, 87h                 ;request for extended move? 
  678.                 jne     short gen_prot100
  679.                 call    emulate_blk_mov         ;if so, we must do it
  680.                 popad
  681.                 mov     ah, 0                   ;default to success
  682.                 jnz     gen_prot299             ;exit if success
  683.                 mov     ah, 3                   ;indicate a20 gate failed
  684.                 jmp     gen_prot299             ;and return
  685.  
  686. gen_prot100:
  687. ;
  688. ;Adjust stack so that error code goes away and int number retrieved from
  689. ;instruction goes in spot on stack where pushed int number is (for stacks
  690. ;with no error code).  Stack will be the way pass_thru routine likes it.
  691. ;
  692.                 mov     ax, bx
  693.                 mov     bx, [bp].e_pushed_bp
  694.                 shl     ebx, 16                 ;get into high word
  695.                 mov     bl, ah                  ;interrupt number
  696.                 mov     [bp].e_errcode, ebx
  697.  
  698.                 cmp     bl, 1                   ;software int 1?
  699.                 jne     short gen_prot140
  700.  
  701. ;Below, check to see if we are already in the debugger.  This is only to
  702. ;handle the unlikely case where there is an actual INT 1 instruction inside
  703. ;of an interrupt handler.  If there is and the debugger is active, the
  704. ;instruction will be ignored.
  705.  
  706.                 popad
  707.                 cmp     int1_active, TRUE       ;already in debugger? 
  708.                 jne     short gen_prot130       ;if not, go enter int 1
  709.                                                         
  710.                                                 ;else ignore it by returning                        
  711.                 add     sp, 2                   ;get rid of int number
  712.                 pop     bp
  713.                 iretd                  
  714.  
  715. gen_prot130:
  716.                 add     sp, 4                   ;error code gone             
  717.                 mov     bp, sp
  718.                 pushad
  719.                 jmp     int_1_210               ;go enter int 1
  720.  
  721. gen_prot140:
  722.                 popad       
  723.                 add     sp, 4                   ;error code gone
  724.                 jmp     pass_thru               ;route the int via vectors        
  725. gen_prot150:
  726.                 cmp     num_io_bp, 0            ;any I/O break points defined?
  727.                 je      short gen_prot400       ;if not, don't look for I/O
  728.  
  729.                 xor     ah, ah                  ;use as string flag
  730.                 cmp     bl, REP_PREFIX          ;rep ?
  731.                 jne     short gen_prot190
  732.                 mov     ah, STRING              ;only string type use rep
  733.                 mov     bl, bh                  ;get 2nd byte
  734. gen_prot190:
  735. ;
  736. ;      If repeat prefix was found, ah now has a flag indicating only
  737. ;      string type I/O instructions should be expected and bl now contains
  738. ;      the byte of object code past the repeat prefix.
  739. ;
  740. ;      Note:  To be complete, this code should also look for the
  741. ;             operand-size prefix  and segment overrides.
  742. ;
  743.                 mov     si, offset io_table
  744.                 mov     cx, IO_TAB_ENTRIES
  745. gen_prot200:
  746.                 or      ah, ah                  ;strings only?
  747.                 jz      short gen_prot225       ;if not, don't test
  748.  
  749.                 test    [si].io_info, ah        ;if table entry is not a string
  750.                 jz      short gen_prot300       ;type I/O, go try next one
  751. gen_prot225:
  752.                 cmp     bl, [si].io_opcode 
  753.                 jne     short gen_prot300
  754.                 mov     io_instrucf, TRUE       ;instruction found
  755.                 mov     cl, [si].io_info        ;get info about instruction
  756.                 mov     io_inst_info, cl        ;save it
  757.                 test    cl, CONSTANT            ;port number in instruction?    
  758.                 jz      short gen_prot250       ;if not, we have it
  759.                 movzx   dx, bh                  ;get port 
  760. gen_prot250:
  761.                 mov     io_inst_port, dx        ;save port 
  762.                 mov     cx, 1                   ;number of bits
  763.                 sub     ah, ah                  ;indicate clear
  764.                 call    do_bit_map     
  765. gen_prot260:
  766.                 
  767.                 bts     [bp].e_eflags, trapf    ;single step i/o
  768.                 popad       
  769. gen_prot299:
  770.  
  771.                 add     sp, 2                   ;int number pushed
  772.                 pop     bp
  773.                 add     sp, 4                   ;error code
  774.                 iretd
  775.  
  776. gen_prot300:
  777.                 add     si, size io_struc       ;advance to next table entry
  778.                 loop    gen_prot200
  779. gen_prot400:
  780. ;
  781. ;Also need to add code here to check for a few other exceptions (e.g.  
  782. ;the HLT instruction).
  783. ;
  784.                 mov     ax, [bp].e_cs           ;get cs of user instruction
  785.                 call    display_it
  786.                 mov     eax, [bp].e_eip         ;add ip 
  787.                 call    display_it
  788.                 popad      
  789.                 mov     ax, [bp].e_pushed_int
  790.                 jmp     fatal_error
  791. gen_prot_isr    endp
  792.  
  793.  
  794. ;--------------------------------------------------------------
  795. ;emulate_blk_mov - Called from gen_prot_isr when an int 15h   |
  796. ;                  function 87h (extended memory block move)  |
  797. ;                  is detected.  Perform the function and     |
  798. ;                  return.                                    |
  799. ;                                                             |
  800. ;                  Enter:                                     |
  801. ;                         es on PL0 stack and SI form a       |
  802. ;                               pointer to user's GDT         |
  803. ;                                                             |
  804. ;                            cx=number of words to move       |
  805. ;                                                             |
  806. ;                   Exit: Indicate success by affecting flags |
  807. ;                         image on PL0 stack.                 |
  808. ;                                                             |
  809. ;                         Zero flag set if error (for now     |
  810. ;                         the only error checked for is       |
  811. ;                         an A20 failure - other error        |
  812. ;                         checks should be added).            |
  813. ;                                                             |
  814. ;--------------------------------------------------------------
  815. emulate_blk_mov proc    near
  816.                 mov     ax, offset gdt_seg:sel_databs ;absolute zero base
  817.                 mov     ds, ax
  818.                 mov     es, ax
  819. ;First, determine if a20 is already set
  820.                 mov     ebx, 100000h            ;1 meg                
  821.                 xor     dl, dl                  ;use dl for a20 flag
  822.                 push    dword ptr [ebx]         ;get contents at "1 meg"
  823.                 mov     eax, 0ffffffffh 
  824.                 mov     dword ptr [ebx], eax    ;move test value there
  825.                 xor     edi, edi
  826.                 cmp     dword ptr [edi], eax    ;did it wrap to zero
  827.                 pop     dword ptr [ebx]         ;restore value
  828.                 je      short emulate_b025      ;if so, a20 not set
  829.                 mov     dl, 1                   ;indicate a20 already set
  830.                 jmp     short emulate_b100     
  831. emulate_b025:
  832.  
  833.                 mov     al, 1                   ;set a20 function
  834.                 call    do_a20
  835.                 jnz     short emulate_b100
  836. emulate_b050:
  837.                 bts     [bp].e_eflags, carry    ;indicate error
  838.                 btr     [bp].e_eflags, zero     
  839.                 ret
  840. emulate_b100:
  841.                 movzx   ebx, [bp].e_es   ;get user's es
  842.                 shl     ebx, 4           ;make linear
  843.                 movzx   esi, si
  844.  
  845.                 mov     eax, 00ffffffh   ;24 bit address only
  846. ;get destination address
  847.                 mov     edi, dword ptr [ebx][esi].ex_mdest.seg_base_low   
  848.                 and     edi, eax         ;24 bit address only
  849.  
  850. ;get source address
  851.                 mov     esi, dword ptr [ebx][esi].ex_msource.seg_base_low   
  852.                 and     esi, eax         ;24 bit address only
  853.  
  854.                 cld
  855.  
  856.                 movzx   ecx, cx         ;word count
  857.                 shr     cx, 1           ;convert to dword count
  858.                 jnc     short emulate_b500  ;if evenly div by 4
  859.  
  860.                 db      67h             ;force 32 bit addressing
  861.                 movsw                   ;move odd one
  862.                 jcxz    emulate_b600    ;if only 1 word was requested
  863. emulate_b500:
  864.                 db      67h             ;force 32 bit addressing
  865.                 rep     movsd           ;move dwords
  866. emulate_b600:
  867.                 test    dl, 1           ;a20 already set when entered?
  868.                 jnz     short emulate_b999
  869.  
  870.                 sub     al, al                  ;clear a20 function
  871.                 call    do_a20
  872.                 jz      short emulate_b050      ;if error
  873.  
  874. emulate_b999:
  875.                 btr     [bp].e_eflags, carry    ;indicate success
  876.                 bts     [bp].e_eflags, zero     
  877.                 ret
  878. emulate_blk_mov endp
  879.  
  880. ;--------------------------------------------------------------
  881. ;do_a20 -  Turn A20 on or off.                                |
  882. ;                                                             |
  883. ;         Enter:                                              |
  884. ;                al=1 turn it on.                             |
  885. ;                al=0 turn it off.                            |
  886. ;                                                             |
  887. ;          Exit: Zero set if error                            |
  888. ;                                                             |
  889. ;     No registers saved.                                     |
  890. ;--------------------------------------------------------------
  891. do_a20          proc    near
  892.                 mov     ah,0dfh        ;a20 on
  893.                 or      al,al
  894.                 jnz     short do_a20_100 
  895.                 mov     ah,0ddh        ;a20 off
  896. do_a20_100:
  897.                 call    key_wait
  898.                 jz      short do_a20_999
  899.                 mov     al,0d1h
  900.                 out     64h,al
  901.                 call    key_wait
  902.                 mov     al,ah
  903.                 out     60h,al
  904.                 call    key_wait
  905.                 jz      short do_a20_999        
  906.                 mov     al,0ffh
  907.                 out     64h,al
  908.                 call    key_wait
  909. do_a20_999:                      
  910.                 ret
  911. do_a20          endp
  912.  
  913. key_wait        proc    near
  914.                 push    cx
  915.                 xor     cx,cx             ;max time out
  916. key_w100:
  917.                 dec     cx
  918.                 jz      short key_w999
  919.                 in      al,64h
  920.                 and     al,2
  921.                 jnz     short key_w100    ;loop if keyboard controller not ready
  922. key_w999:       or      cx,cx             ;return with zero set if error
  923.                 pop     cx
  924.                 ret
  925. key_wait        endp
  926.  
  927. ;----------------------------------------------------------------------
  928. ; do_debug_reg - enable/disable debug register for break point.       |
  929. ;                                                                     |
  930. ;             Enter: ch = 0 if clearing break point                   |
  931. ;                    ch = 1 if setting break point                    |
  932. ;                    ch = 2 if setting up break point type and        |
  933. ;                           address, but not enabling yet             |
  934. ;                                                                     |
  935. ;                    ch = 3 get bn portion of debug status register   |
  936. ;                           into ax (then clear status register)      |
  937. ;                                                                     |
  938. ;                    if clearing and eax !=0, eax holds other         |
  939. ;                    bits to be cleared (used for also clearing       |
  940. ;                    ge or le bits)                                   |
  941. ;                                                                     |
  942. ;                    cl = debug register number (0-3)                 |
  943. ;                                                                     |
  944. ;                    if setting also have:                            |
  945. ;                                                                     |
  946. ;                    al = length (0=1 byte, 1=2 bytes, 3=4 bytes)     |
  947. ;                    ah = type (0=execution, 1=write, 3=read/write)   |
  948. ;                   edx = linear address for break                    |
  949. ;                                                                     |
  950. ;                   also, if al='*' simply reactivate the break       |
  951. ;                   point keeping the existing type and address.      |
  952. ;                                                                     |
  953. ;              Exit: if disabling, specified debug register break     |
  954. ;                    point is disabled.                               |
  955. ;                                                                     |
  956. ;                    if enabling, specified debug register is loaded  |
  957. ;                    and break point is enabled.                      |
  958. ;                                                                     |
  959. ;                    if getting debug status register, bn portion of  |
  960. ;                    DR6 is returned in AX.                           |
  961. ;                                                                     |
  962. ;  Save ebx.                                                          |
  963. ;----------------------------------------------------------------------
  964. do_debug_reg    proc    near
  965.  
  966.                 cmp     ch, 3                   ;requesting status?
  967.                 jne     short do_deb050         ;if not
  968.                 mov     eax, dr6                ;debug status register
  969.                 xor     edx, edx
  970.                 mov     dr6, edx                ;clear status
  971.                 and     ax, 0fh                 ;isolate bn status
  972.                 ret                             ;and return
  973. do_deb050:
  974.                 push    ebx
  975.                 mov     ebx, dr7                ;get debug control reg
  976.                 cmp     ch, 1                   ;determine function
  977.                 jb      short do_deb850         ;if clear function go do it
  978.                 ja      short do_deb100         ;setup, but not enable 
  979.                 cmp     al, '*'                 ;simply reset?
  980.                 je      short do_deb850
  981. do_deb100:
  982.                 push    cx                      ;save function/reg #
  983.                 push    edx                     ;save linear address
  984.                 mov     edx, 0fh                ;4 on bits
  985.                 shl     cl, 2                   ;reg # * bits associated        
  986.                 add     cl, 16                  ;upper portion of 32 bit reg
  987.                 shl     edx, cl
  988.                 not     edx                     ;associated bits off
  989.                 and     ebx, edx                ;in the dr7 value
  990.                 shl     al, 2                   ;length bits to len position
  991.                 or      al, ah                  ;put in the type
  992.                 mov     dl, ah                  ;save type
  993.                 sub     ah, ah
  994.                 shl     eax, cl                 ;move len/rw to position
  995.                 or      ebx, eax
  996.                 or      dl, dl                  ;execution type?
  997.                 jz      short do_deb500         ;if so, don't need ge
  998.                 bts     bx, ge_bit
  999. do_deb500:
  1000.  
  1001.                 pop     edx                     ;restore linear address
  1002.                 pop     cx                      ;and debug register #
  1003.                 cmp     cl, 1
  1004.                 je      short do_deb600
  1005.                 ja      short do_deb700
  1006.                 mov     dr0, edx
  1007.                 jmp     short do_deb800
  1008. do_deb600:
  1009.                 mov     dr1, edx
  1010.                 jmp     short do_deb800
  1011. do_deb700:
  1012.                 cmp     cl, 3
  1013.                 je      short do_deb750
  1014.                 mov     dr2, edx
  1015.                 jmp     short do_deb800
  1016. do_deb750:
  1017.                 mov     dr3, edx
  1018. do_deb800:
  1019.                 cmp     ch, 2                   ;setup, but not enable?
  1020.                 je      short do_deb900         ;if so, skip enable
  1021. do_deb850:
  1022.                 shl     cl, 1                   ;get to global enable for #
  1023.                 inc     cl          
  1024.                 movzx   dx, cl                  ;bit number to turn on
  1025.                 bts     bx, dx                  ;set on in dr7 value
  1026.                 or      ch, ch                  ;set function?
  1027.                 jnz     short do_deb900
  1028.                 btr     bx, dx                  ;if not, disable break
  1029.                 or      ax, ax                  ;clear ge or le?
  1030.                 jz      short do_deb900         ;if not continue
  1031.                 btr     bx, ax                  ;if so, clear ge or le bit
  1032. do_deb900:
  1033.                 mov     dr7, ebx                ;put adjusted value back        
  1034.                 pop     ebx
  1035. do_deb999:
  1036.                 ret
  1037. do_debug_reg    endp
  1038.  
  1039. isrcode         ends
  1040.                 end
  1041.